package com.notary.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.base.Charsets;
import com.google.common.hash.Hashing;
import com.notary.entity.SysUser;
import com.notary.entity.po.H5FaceDTO;
import com.notary.entity.vo.JsonResult;
import com.notary.service.SysUserService;
import com.notary.util.HttpUtils;
import com.notary.util.JwtUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;


@RestController
@Api(value = "人脸识别", description = "人脸识别")
@RequestMapping("/face")
@Slf4j
public class FaceController {
    @Autowired
    RedisTemplate<String, Object> redisTemplate;
    @Value("${tencent.face.version}")
    private String version;

    @Value("${tencent.face.appid}")
    private String appid;

    @Value("${tencent.face.secret}")
    private String secret;

    @Autowired
    private SysUserService sysUserService;

    @ApiOperation(value = "test")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "查询成功", response = JsonResult.class)})
    @PostMapping("/h5")
    public JsonResult h5(@RequestBody H5FaceDTO h5FaceDTO) {
        String userId = "";
        String name = "";
        String idNo = "";
        String orderNo = "";
        if (StringUtils.isEmpty(h5FaceDTO.getUserId())) {
            return JsonResult.fail("userId不能为");
        } else {
            userId = h5FaceDTO.getUserId();
        }
        if (StringUtils.isEmpty(h5FaceDTO.getName())) {
            return JsonResult.fail("name不能为");
        } else {
            name = h5FaceDTO.getName();

        }
        if (StringUtils.isEmpty(h5FaceDTO.getIdNo())) {
            return JsonResult.fail("idNo不能为");
        } else {
            idNo = h5FaceDTO.getIdNo();
        }
        if (StringUtils.isEmpty(h5FaceDTO.getOrderNo())) {
            return JsonResult.fail("OrderNo不能为空");
        } else {
            orderNo = h5FaceDTO.getOrderNo();
        }

        // String orderNo=this.generateOrderNo("");
        String access_token = get_access_token();

        String SIGN_ticket = get_SIGN_ticket(access_token);

        String NONCE_ticket = get_NONCE_ticket(access_token, userId);
        if (access_token.equals("1")) {
            return JsonResult.fail("获取access_token 失败");
        }
        if (SIGN_ticket.equals("1")) {
            return JsonResult.fail("获取SIGN_ticket 失败");
        }
        if (NONCE_ticket.equals("1")) {
            return JsonResult.fail("获取NONCE_ticket 失败");
        }
        // String h5faceId=getFaceId( appid, orderNo, name, idNo, userId, SIGN_ticket, version);
        String h5faceId = "";
        JSONObject faceIdObject = getFaceId(appid, orderNo, name, idNo, userId, SIGN_ticket, version);
        if (faceIdObject.getString("code").equals("1")) {
            return JsonResult.fail("获取h5faceId失败：" + faceIdObject.getString("msg"));
        } else {
            h5faceId = faceIdObject.getString("data");
        }


        String nonce = getItemID(32);
    /*    HashMap queryParas5 = new HashMap ();
        queryParas5.put("webankAppId",appid);
        queryParas5.put("version","1.0.0");
        queryParas5.put("nonce",nonce);
        queryParas5.put("orderNo",orderNo);
        queryParas5.put("h5faceId",h5faceId);
        queryParas5.put("url",reurl);
        queryParas5.put("userId",userId);*/

//wbappid、userId、orderNo、version、h5faceId、ticket、nonce
        List<String> listStr = new ArrayList();
        listStr.add(version);
        listStr.add(appid);
        listStr.add(h5faceId);
        listStr.add(orderNo);
        //nonce
        listStr.add(nonce);
        listStr.add(userId);
       /* queryParas5.put("sign",sign(listStr,NONCE_ticket));
        queryParas5.put("from","browser");
        queryParas5.put("redirectType","1");*/
        log.info("listStr:" + listStr);
        String sign = sign(listStr, NONCE_ticket);
        String url = "https://ida.webank.com/api/web/login";
        url = url + "?webankAppId=" + appid + "&version=" + version + "&nonce=" + nonce + "&orderNo=" + orderNo + "&h5faceId=" + h5faceId
                + "&resultType=1" + "&userId=" + userId + "&sign=" + sign + "&from=browser&redirectType=1";
        JSONObject object = new JSONObject();
        object.put("orderNo", orderNo);
        object.put("url", url);
        object.put("userId", h5FaceDTO.getUserId());
      /*  log.info(queryParas5.toString());
        String a=HttpUtils.get("https://ida.webank.com/api/web/login",queryParas5);*/
        // object.put("VIE",a);
        return JsonResult.success(object);
    }

    /**
     * 身份认证查询接口
     */
    @ApiOperation(value = "身份认证查询接口")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "身份认证查询接口", response = JsonResult.class)})
    @PostMapping("/getResult")
    public JsonResult getResult(@RequestBody H5FaceDTO dto) {
        String access_token = get_access_token();
        String NONCE_ticket = get_SIGN_ticket(access_token);
        List<String> listStr = new ArrayList();
        listStr.add(appid);
        listStr.add(dto.getOrderNo());
        listStr.add(version);
        String nonceStr = getItemID(32);
        //nonceStr
        listStr.add(nonceStr);
        String url = "https://idasc.webank.com/api/server/sync";
        String sign = sign(listStr, NONCE_ticket);
        HashMap queryParas = new HashMap();
        queryParas.put("app_id", appid);
        queryParas.put("version", version);
        queryParas.put("nonce", nonceStr);
        queryParas.put("order_no", dto.getOrderNo());
        queryParas.put("sign", sign);
        log.info("PC返回校验结果请求参数：" + queryParas);
        String result = HttpUtils.get(url, queryParas);
        JSONObject jsonObject = JSON.parseObject(result);
        log.info("PC返回校验结果：" + jsonObject);
        String code = jsonObject.getString("code");
        SysUser user = sysUserService.getOne(new QueryWrapper<SysUser>().eq("user_id", dto.getUserId()));
        if (code.equals("0")) {
            String token = JwtUtil.createJWT(user, JwtUtil.JWT_TTL);
            String tokenStr = JwtUtil.TOKEN_PREFIX + token;
            redisTemplate.opsForValue().set(user.getUsername(), tokenStr, 30, TimeUnit.DAYS);
            return JsonResult.success(tokenStr);
        } else if (code.equals("66660004")) {
            //人脸匹配度
            String returStr = jsonObject.getString("result");
            JSONObject jsonObject1 = JSON.parseObject(returStr);
            BigDecimal similarity = jsonObject1.getBigDecimal("similarity");
            if (similarity.compareTo(new BigDecimal(75)) > -1) {
                String token = JwtUtil.createJWT(user, JwtUtil.JWT_TTL);
                String tokenStr = JwtUtil.TOKEN_PREFIX + token;
                redisTemplate.opsForValue().set(user.getUsername(), tokenStr, 30, TimeUnit.DAYS);
                return JsonResult.success(tokenStr);
            }
        }
        return JsonResult.fail("0", jsonObject);
    }
/*    @ApiOperation(value = "身份认证查询接口")
    @ApiResponses(value = { @ApiResponse(code = 200, message = "身份认证查询接口", response = JSONResult.class) })
    @PostMapping("/test")
    public void getResult(){
        String token = JwtUtil.generateToken("370828db6392a324026196fa5ba7000q");
        redisTemplate.opsForValue().set("office_user_token:" + "370828db6392a324026196fa5ba7000q", token, 1, TimeUnit.DAYS);

    }*/

    /**
     * 身份认证查询接口
     */
    @ApiOperation(value = "H5身份认证查询接口")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "身份认证查询接口", response = JsonResult.class)})
    @PostMapping("/getResultH5")
    // @LoginOfficeUserFaceRequired
    public JsonResult getResultH5(@RequestBody H5FaceDTO dto) {
        String access_token = get_access_token();
        String NONCE_ticket = get_SIGN_ticket(access_token);
        List<String> listStr = new ArrayList();
        listStr.add(appid);
        listStr.add(dto.getOrderNo());
        listStr.add(version);
        String nonceStr = getItemID(32);
        //nonceStr
        listStr.add(nonceStr);
        String url = "https://idasc.webank.com/api/server/sync";
        String sign = sign(listStr, NONCE_ticket);
        HashMap queryParas = new HashMap();
        queryParas.put("app_id", appid);
        queryParas.put("version", version);
        queryParas.put("nonce", nonceStr);
        queryParas.put("order_no", dto.getOrderNo());
        queryParas.put("sign", sign);
        log.info("H5返回校验结果请求参数：" + queryParas);
        String result = HttpUtils.get(url, queryParas);
        JSONObject jsonObject = JSON.parseObject(result);
        log.info("H5返回校验结果：" + jsonObject);
        String code = jsonObject.getString("code");
     /*   if(code.equals("0")){
            return   JSONResult.success("");
        }else{
            return   JSONResult.fail(jsonObject.getString("msg"));
        }
*/

        if (code.equals("0")) {
            return JsonResult.success("");
        } else {
            //人脸匹配度
            if (code.equals("66660004")) {
                String returStr = jsonObject.getString("result");
                JSONObject jsonObject1 = JSON.parseObject(returStr);
                BigDecimal similarity = jsonObject1.getBigDecimal("similarity");
                if (similarity.compareTo(new BigDecimal(75)) > -1) {
                    return JsonResult.success("");
                } else {
                    return JsonResult.fail(jsonObject.getString("msg"));
                }
            }
            return JsonResult.fail(jsonObject.getString("msg"));
        }


    }


    private String get_access_token() {
        JSONObject jsonObject = new JSONObject();
        String url = "https://idasc.webank.com/api/oauth2/access_token?app_id=" + appid + "&secret=" + secret +
                "&grant_type=client_credential&version=" + version;
        String body = jsonObject.toJSONString();
        System.out.println("body = " + body);
        String result = HttpUtils.get(url);
        log.info("result=get_access_token:" + result);
        JSONObject jsonObject1 = JSON.parseObject(result);

        String code = jsonObject1.getString("code");

        JSONObject returnJson = new JSONObject();
        if (code.equals("0")) {
            String access_token = jsonObject1.getString("access_token");
            log.info("access_token:" + access_token);
            returnJson.put("cdoe", "0");
            returnJson.put("data", access_token);
            return access_token;
        } else {
            returnJson.put("code", 1);
            returnJson.put("data", returnJson.getString("msg"));
            return "1";
        }


    }


    private String get_SIGN_ticket(String access_token) {
        String url = " https://idasc.webank.com/api/oauth2/api_ticket?app_id=" + appid + "&access_token=" + access_token +
                "&type=SIGN&version=" + version;
        String result = HttpUtils.get(url);
        log.info("result=get_SIGN_ticket:" + result);
        JSONObject jsonObject = JSON.parseObject(result);
        String code = jsonObject.getString("code");
        if (code.equals("0")) {
            String a = jsonObject.getString("tickets");
            jsonObject = JSONArray.parseArray(a).getJSONObject(0);
            String SIGN_ticket = jsonObject.getString("value");
            log.info("SIGN_ticket:" + SIGN_ticket);
            return SIGN_ticket;
        } else {
            return "1";
        }

    }

    private String get_NONCE_ticket(String access_token, String userId) {
        String url = " https://idasc.webank.com/api/oauth2/api_ticket?app_id=" + appid + "&access_token=" + access_token +
                "&type=NONCE&version=" + version + "&user_id=" + userId;

        String result = HttpUtils.get(url);
        log.info("result=get_NONCE_ticket:" + result);
        JSONObject jsonObject = JSON.parseObject(result);
        String code = jsonObject.getString("code");
        if (code.equals("0")) {
            String a = jsonObject.getString("tickets");
            jsonObject = JSONArray.parseArray(a).getJSONObject(0);
            String NONCE_ticket = jsonObject.getString("value");
            log.info("NONCE_ticket:" + NONCE_ticket);
            return NONCE_ticket;
        } else {
            return "1";
        }

    }

    private JSONObject getFaceId(String appid, String orderNo, String name, String idNo, String userId, String SIGN_ticket, String version) {
        String url = "https://idasc.webank.com/api/server/h5/geth5faceid";
        JSONObject queryParas = new JSONObject();
        queryParas.put("webankAppId", appid);
        queryParas.put("orderNo", orderNo);
        queryParas.put("name", name);
        queryParas.put("idNo", idNo);
        queryParas.put("userId", userId);
        queryParas.put("version", version);
        List<String> listStr = new ArrayList();
        listStr.add("1.0.0");
        listStr.add(idNo);
        listStr.add(appid);
        listStr.add(orderNo);
        listStr.add(name);
        listStr.add(userId);
        queryParas.put("sign", sign(listStr, SIGN_ticket));
        log.info("======sign" + sign(listStr, SIGN_ticket));
        String body = queryParas.toJSONString();
        String result = HttpUtils.post(url, body, "application/json");
        log.info("result:" + result);
        JSONObject jsonObject = JSON.parseObject(result);
        String code = jsonObject.getString("code");

        JSONObject returnJson = new JSONObject();

        if (code.equals("0")) {
            String h5faceId = jsonObject.getJSONObject("result").getString("h5faceId");
            log.info("h5faceId:" + h5faceId);
            returnJson.put("code", 0);
            returnJson.put("data", h5faceId);
            // return h5faceId;
            return returnJson;
        } else {
            returnJson.put("code", 1);
            returnJson.put("msg", jsonObject.getString("msg"));
            // return "1";
            return returnJson;
        }

    }

    private String generateOrderNo(String phone) {
        StringBuilder sb = new StringBuilder();
        String date = new SimpleDateFormat("yyyyMMdd").format(new Date());
        String key = "REDIS_KEY_PREFIX_ORDER_ID" + date;
        Long increment = redisTemplate.opsForValue().increment(key, 1);
        if (increment == 1) {
            redisTemplate.expire(key, 24, TimeUnit.HOURS);// 设置失效时间 每天从1开始
        }
        sb.append(date);
        //  sb.append(phone.substring(phone.length() - 4));
        String incrementStr = increment.toString();
        if (incrementStr.length() <= 6) {
            sb.append(String.format("%06d", increment));
        } else {
            sb.append(incrementStr);
        }
        return "F" + sb.toString();
    }


    public static String sign(List<String> values, String ticket) {
        if (values == null) {
            throw new NullPointerException("values is null");
        }
        values.removeAll(Collections.singleton(null));// remove null
        values.add(ticket);
        java.util.Collections.sort(values);

        StringBuilder sb = new StringBuilder();
        for (String s : values) {
            sb.append(s);
        }
        return Hashing.sha1().hashString(sb, Charsets.UTF_8).toString().toUpperCase();
    }

    private static String getItemID(int n) {
        String val = "";
        Random random = new Random();
        for (int i = 0; i < n; i++) {
            String str = random.nextInt(2) % 2 == 0 ? "num" : "char";
            if ("char".equalsIgnoreCase(str)) { // 产生字母
                int nextInt = random.nextInt(2) % 2 == 0 ? 65 : 97;
                // System.out.println(nextInt + "!!!!"); 1,0,1,1,1,0,0
                val += (char) (nextInt + random.nextInt(26));
            } else if ("num".equalsIgnoreCase(str)) { // 产生数字
                val += String.valueOf(random.nextInt(10));
            }
        }
        return val;
    }
}

